package cn.lizemin.builder.version1.entity;

/**
 * @author lzm
 * @version 1.0
 * @description: 资源池的配置类的设计，要求满足以下需求
 * 需求：
 *   资源名称（name): 必填
 *   最大总资源数量（）：非必填，默认值：8
 *   最大空闲资源数量：非必填，默认值：8
 *   最小空闲资源数量：非必填，默认值：0
 * @date 2022/4/28 10:28
 */
public class ResourcePoolConfig {
    private String name;
    private int maxTotal;
    private int maxIdle;
    private int minIdle;

    public String getName() {
        return name;
    }

    public int getMaxTotal() {
        return maxTotal;
    }

    public int getMaxIdle() {
        return maxIdle;
    }

    public int getMinIdle() {
        return minIdle;
    }

    /**
     * 将builder对象校验过后的属性复制给ResourcePoolConfig对象
     * @param builder
     */
    private ResourcePoolConfig(Builder builder) {
        //这里用builder.name而不是builder.getName(), 是因为Builder没有get方法
        //而且Builder是一个内部类，其属性是private修饰的，只能在这个类文件中（ResourcePoolConfig）这样使用
        this.name = builder.name;
        this.maxTotal = builder.maxTotal;
        this.maxIdle = builder.maxIdle;
        this.minIdle = builder.minIdle;
    }

    /**
     * 该对象只是用来做参数校验，最终返回一个带有正确参数的对象
     */
    public static class Builder {
        /**
         * 定义默认值常量,提升程序可读性，对数据进行解释
         */
        private static final int DEFAULT_MAX_TOTAL = 8;
        private static final int DEFAULT_MAX_IDLE = 8;
        private static final int DEFAULT_MIN_IDLE = 0;

        /**资源名称*/
        private String name ;

        /**
         * 对属性设置默认值
         */
        private int maxTotal = DEFAULT_MAX_TOTAL;
        private int maxIdle = DEFAULT_MAX_IDLE;
        private int minIdle = DEFAULT_MIN_IDLE;

        /**
         * 这里主要校验参数间的依赖大小比对，
         * 这是本类中唯一的公共方法，也是其他所有private方法的代表，或者入口
         * 所以这个public方法中的逻辑其实是由该方法中的代码块+其调用的private方法
         * @return
         */
        public ResourcePoolConfig build() {
            // 校验逻辑放到这里来做，包括必填项校验、依赖关系校验、约束条件校验等
            if (name == null || name.equals("")) {
                throw new IllegalArgumentException("资源名称为必填项！");
            }

            if (maxIdle > maxTotal) {
                throw new IllegalArgumentException("最大资源总量必须大于最大空闲资源量！");
            }

            if (minIdle > maxTotal || minIdle > maxIdle) {
                throw new IllegalArgumentException("最小空闲数量不能小于最大资源总量或者最大空闲数量！");
            }

//            通过外部类的构造器来将数据复制给其属性，同时返回目标对象，就好像变魔术一样
            return new ResourcePoolConfig(this);

        }

        public Builder setName(String name) {
            if (name == null || name.equals("")) {
                throw new IllegalArgumentException("资源名称为必填项！");
            }
            this.name = name;
            /**
             * return this ：用于实现链式调用
             */
            return this;
        }

        public Builder setMaxTotal(int maxTotal) {
            if (maxTotal <= 0) {
                throw new IllegalArgumentException("最大资源总数必须大于0！");
            }
            this.maxTotal = maxTotal;
            /**
             * return this ：用于实现链式调用
             */
            return this;
        }

        public Builder setMaxIdle(int maxIdle) {
            if (maxIdle < 0) {
                throw new IllegalArgumentException("最大闲置资源数量必须大于等于0！");
            }
            this.maxIdle = maxIdle;
            /**
             * return this ：用于实现链式调用
             */
            return this;
        }

        public Builder setMinIdle(int minIdle) {
            if (minIdle < 0) {
                throw new IllegalArgumentException("最小闲置资源数量必须大于等于0！");
            }

            this.minIdle = minIdle;
            /**
             * return this ：用于实现链式调用
             */
            return this;
        }
    }

}
